import config from '@/common/config.js';
import store from '@/common/store.js';
import axios from 'axios';
import lodash from 'lodash'; //一个工具包
import Clipboard from 'clipboard';
import cookie from 'vue-cookies';

import {
	Notification
} from 'element-ui';
import md5 from "js-md5";

const baseVM = {
	props: {
		value: {
			type: Object | Array
		},
		//是否展示列表的分页
		showPage: {
			type: Boolean,
			default: true
		},
		//表单的宽度参数
		labelWidth: {
			type: String,
			default: "120px"
		},
		//表单的inline
		inline: {
			type: Boolean,
			default: false
		},
		inline2: {
			type: Boolean,
			default: true
		},
		//展示操作列的条件
		showOp: {
			type: Boolean,
			default: true
		}
	},
	watch: {
		model: {
			handler: function (n, o) {
				if (this.recordValue == false) return;
				if (this.isAdd == false) return;
				if (this.loadBeforeValSuccess == false) return;
				//console.log("watch.model", JSON.stringify(n));
				tool.setItem(this.$route.path, n);
			},
			deep: true,
			immediate: true
		}
	},
	data() {
		var lan = config.getLanguageJs(); //多语言

		return {
			isAdd: false,
			visible: false,
			visible2: false,
			visible3: false,
			loading: false,
			loading2: false,
			loading3: false,
			list: [],
			list2: [],
			list3: [],
			total: 0,
			total2: 0,
			total3: 0,
			search: {
				index: 1,
				size: 10
			},
			search2: {
				index: 1,
				size: 10
			},
			search3: {
				index: 1,
				size: 10
			},
			//model: {},
			routePath: "", //路由路径
			componentTag: "", //组件名称

			pickerOptions: {
				// disabledDate(time) {
				//     return time.getTime() > Date.now();
				// },
				shortcuts: [{
					text: lan["today"],
					onClick(picker) {
						picker.$emit('pick', new Date());
					}
				}, {
					text: lan["yesterday"],
					onClick(picker) {
						const date = new Date();
						date.setTime(date.getTime() - 3600 * 1000 * 24);
						picker.$emit('pick', date);
					}
				}, {
					text: lan["beforeYesterday"],
					onClick(picker) {
						const date = new Date();
						date.setTime(date.getTime() - 3600 * 1000 * 24 * 2);
						picker.$emit('pick', date);
					}
				}, {
					text: lan["aWeekAgo"],
					onClick(picker) {
						const date = new Date();
						date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
						picker.$emit('pick', date);
					}
				}]
			},

			cmOption: {
				tabSize: 1, // tab
				styleActiveLine: true, // 高亮选中行
				lineNumbers: true, // 显示行号
				styleSelectedText: true,
				line: true,
				foldGutter: true, // 块槽
				gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
				highlightSelectionMatches: {
					showToken: /\w/,
					annotateScrollbar: true
				}, // 可以启用该选项来突出显示当前选中的内容的所有实例
				// 模式, 可查看 codemirror/mode 中的所有模式
				mode: "text/x-mssql", //text/ecmascript
				// hint.js options
				hintOptions: {
					// 当匹配只有一项的时候是否自动补全
					completeSingle: false
				},
				// 快捷键 可提供三种模式 sublime、emacs、vim
				//keyMap: 'sublime',
				matchBrackets: true,
				showCursorWhenSelecting: true,
				theme: 'eclipse', // 主题 
				extraKeys: {
					'Ctrl': 'autocomplete'
				} //可以用于为编辑器指定额外的键绑定，以及keyMap定义的键绑定
			},

			cmOptionCSharp: {
				tabSize: 1, // tab
				styleActiveLine: true, // 高亮选中行
				lineNumbers: true, // 显示行号
				styleSelectedText: true,
				line: true,
				foldGutter: true, // 块槽
				gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
				highlightSelectionMatches: {
					showToken: /\w/,
					annotateScrollbar: true
				}, // 可以启用该选项来突出显示当前选中的内容的所有实例
				// 模式, 可查看 codemirror/mode 中的所有模式
				mode: "text/x-csharp", //text/x-csharp
				// hint.js options
				hintOptions: {
					// 当匹配只有一项的时候是否自动补全
					completeSingle: false
				},
				// 快捷键 可提供三种模式 sublime、emacs、vim
				//keyMap: 'sublime',
				matchBrackets: true,
				showCursorWhenSelecting: true,
				theme: 'eclipse', // 主题 
				extraKeys: {
					'Ctrl': 'autocomplete'
				} //可以用于为编辑器指定额外的键绑定，以及keyMap定义的键绑定
			},

			//读取之前记录的值
			loadBeforeValSuccess: false,

			useVirtual: true,

			button: {
				查询: true,
				新建: true,
				编辑: true,
				启用禁用: true,
				删除: true,
				导出: true,
			}
		};
	},
	computed: {
		comLan() { //所有
			var r = this.comLanMethod();
			if (r == null) return {};
			return r;
		},
		lan() { //带路由路径的lan页面自定义
			var r = this.lanMethod();
			if (r == null) return {};
			return r;
		},
		keyLan() { //key属性里的
			var r = this.keyLanMethod();
			if (r == null) return {};
			return r;
		},
		enumLan() { //所有
			var r = this.enumLanMethod();
			if (r == null) return {};
			return r;
		},
		user() {
			var user = this.$store.state.user;
			return user;
		},

		recordValue() {
			var r = !!this.$store.state.theme.recordValue;
			return r;
		},

		isWechat() {
			var r = isWechat();
			return r;
		},
		buttonParent() {
			var r = this.button;
			return r;
		}
	},
	created() {
		getTokenFromAjax(() => {
			this.locationUrl = config.webapiUrl;
			this.routePath = this.$route.path;
			this.componentTag = this.$options._componentTag;
			if (!!this.componentTag) {
				window[this.routePath + "/" + this.componentTag] = this;
			} else {
				window[this.routePath] = this;
			}
			config.commonBaseVMInit(this);

			this.init();
		}, true);
	},
	beforeDestroy() {
		this.beforeDestroy();
	},
	destroyed() { },
	methods: {
		replaceID(name) {
			if (name == null) return '';
			var id = "ID";
			var index = name.lastIndexOf(id);
			if (index == (name.length - id.length)) {
				return name.substr(0, index);
			}
			return name;
		},

		emptyArray(arr) {
			if (arr == null) return [];
			return arr;
		},

		isListPage(path) {
			if (!path) path = this.$route.path;
			if (path.indexOf('SysDicList') != -1 || path.indexOf('SysSettingList') != -1 || path.indexOf(
				'SysEmployeeList') != -1 || path.indexOf('SysRolePostList') != -1 || path.indexOf(
					'StatisticalSqlList') != -1 || path.indexOf('SysPrintTemplateList') != -1) {
				return false;
			}
			var index = path.lastIndexOf('List');
			if (index == -1) return false;
			if ((index + 'List'.length) >= (path.length - 5)) {
				return true;
			}
			index = path.lastIndexOf('ListNew');
			if (index == -1) return false;
			if ((index + 'ListNew'.length) >= (path.length - 5)) {
				return true;
			}
			return false;
		},
		isAddPage(path) {
			if (!path) path = this.$route.path;
			var index = path.lastIndexOf('Add');
			if (index == -1) return false;
			if ((index + 'Add'.length) >= (path.length - 2)) {
				return true;
			}
			index = path.lastIndexOf('AddNew');
			if (index == -1) return false;
			if ((index + 'AddNew'.length) >= (path.length - 8)) {
				return true;
			}
			index = path.lastIndexOf('AddRedict');
			if (index == -1) return false;
			if ((index + 'AddRedict'.length) >= (path.length - 8)) {
				return true;
			}
			index = path.lastIndexOf('AddRedictNew');
			if (index == -1) return false;
			if ((index + 'AddRedictNew'.length) >= (path.length - 8)) {
				return true;
			}
			return false;
		},

		rowKey(row) {
			console.log("rowKey", row);
			return Math.random();
		},
		checkChinese(val) {
			var reg = new RegExp("[\\u4E00-\\u9FFF]+", "g");
			return reg.test(val);
		},

		loadDefaultSearch(callback) {
			var path = this.$route.path;
			var r = tool.getItem(path + "_search");
			if (!!r) {
				var json;
				try {
					json = JSON.parse(r);
				} catch (e) {
					json = {};
				}
				this.search = Object.assign(this.search, json);
			}
			if (typeof (callback) == "function") callback();
		},
		loadBeforeVal() {
			if (this.model == null) return;
			var path = this.$route.path;
			var json;
			var r;
			r = tool.getItem(path + "_model");
			if (!!r) {
				try {
					json = JSON.parse(r);
				} catch (e) {
					json = {};
				}
				this.model = Object.assign(this.model, json);
			}
			if (this.recordValue == false) return;
			if (this.isAdd == false) return;
			r = tool.getItem(path);
			if (!!r) {
				try {
					json = JSON.parse(r);
				} catch (e) {
					json = {};
				}
				//console.log("loadBeforeVal", json);
				this.model = Object.assign(this.model, json);
			}
			this.loadBeforeValSuccess = true;
		},
		clearBeforeVal() {
			if (this.isAdd == false) return;
			var name = this.$route.path;
			tool.removeItem(name);
		},
		sizeChangeParent(val) {
			var p = this.$parent;
			if (p.sizeChange != null) p.sizeChange();
		},
		indexChangeParent(val) {
			var p = this.$parent;
			if (p.indexChange != null) p.indexChange();
		},
		getListParent() {
			var p = this.$parent;
			if (p.search != null) p.search.index = 1;
			if (p.getList != null) p.getList();
		},
		btnAddParent() {
			var p = this.$parent;
			if (p.btnAdd != null) p.btnAdd();
		},
		btnExportParent() {
			var p = this.$parent;
			if (p.btnExport != null) p.btnExport();
		},
		btnEditParent(scope) {
			var p = this.$parent;
			if (p.btnEdit != null) p.btnEdit(scope);
		},
		btnEnumStatusParent(scope, status) {
			var p = this.$parent;
			if (p.btnEnumStatus != null) p.btnEnumStatus(scope, status);
		},
		btnDelParent(scope) {
			var p = this.$parent;
			if (p.btnDel != null) p.btnDel(scope);
		},

		getListCurrent() {
			if (this.search != null) this.search.index = 1;
			if (this.getList != null) this.getList();
		},
		getListCurrent2() {
			if (this.search2 != null) this.search2.index = 1;
			if (this.getList2 != null) this.getList2();
		},
		getListCurrent3() {
			if (this.search3 != null) this.search3.index = 1;
			if (this.getList3 != null) this.getList3();
		},
		exportFile(name, refName) {
			if (!name) name = this.comLan["btnExport"];
			if (!refName) refName = 'table';
			this.baseExportExcel2(refName, name);
		},
		sizeChange(val) {
			this.search.index = 1;
			this.search.size = val;
			this.getList();
		},
		indexChange(val) {
			this.search.index = val;
			this.getList();
		},
		getSearchData() {
			var r = this.toKeyValue(this.search);
			return r;
		},
		getListByUrl(url, callback) {
			this.loading = true;
			this.post(url, this.getSearchData()).then(data => {
				this.list = data.Result;
				this.total = data.Total;
				this.loading = false;
				if (!!callback && typeof (callback) == "function") callback();
			}).catch(error => {
				this.loading = false;
			});
		},
		sizeChange2(val) {
			this.search2.index = 1;
			this.search2.size = val;
			this.getList2();
		},
		indexChange2(val) {
			this.search2.index = val;
			this.getList2();
		},
		getSearchData2() {
			var r = this.toKeyValue(this.search2);
			return r;
		},
		getListByUrl2(url, callback) {
			this.loading2 = true;
			this.post(url, this.getSearchData2()).then(data => {
				this.list2 = data.Result;
				this.total2 = data.Total;
				this.loading2 = false;
				if (!!callback && typeof (callback) == "function") callback();
			}).catch(error => {
				this.loading2 = false;
			});
		},
		sizeChange3(val) {
			this.search3.index = 1;
			this.search3.size = val;
			this.getList3();
		},
		indexChange3(val) {
			this.search3.index = val;
			this.getList3();
		},
		getSearchData3() {
			var r = this.toKeyValue(this.search3);
			return r;
		},
		getListByUrl3(url, callback) {
			this.loading3 = true;
			this.post(url, this.getSearchData3()).then(data => {
				this.list3 = data.Result;
				this.total3 = data.Total;
				this.loading3 = false;
				if (!!callback && typeof (callback) == "function") callback();
			}).catch(error => {
				this.loading3 = false;
			});
		},
		comLanMethod() { //所有
			var lang = this.$store.state.language;
			if (lang == null) return {};
			return lang;
		},
		lanMethod() { //带路由路径的lan页面自定义
			var lang = this.comLanMethod();
			var path = this.$route.path;
			var r = lang[path];
			if (r == null) return {};
			return r;
		},
		keyLanMethod() { //key属性里的
			var lang = this.comLanMethod();
			var key = lang["Key"];
			if (key == null) return {};
			var path = this.$route.path;
			var arr = path.split('/');
			var last = arr[arr.length - 1];
			if (last == null || last == "") return {};
			var arrReplace = ["addEdit", "addRedict", "add", "listEdit", "listSearch", "listSelect", "listTable",
				"list",
				"main"
			];
			var arrReplace2 = ["new1", "new2", "new3", "new", ""];
			var modelName = last;
			for (var i = 0; i < arrReplace.length; i++) {
				var item = arrReplace[i];
				for (var j = 0; j < arrReplace2.length; j++) {
					var item2 = arrReplace2[j];
					var reg = new RegExp(item + item2, "ig");
					modelName = modelName.replace(reg, "");
				}
			}
			var r = key[modelName];
			return r;
		},
		enumLanMethod() { //key属性里的
			var lang = this.comLanMethod();
			var key = lang["Key"];
			if (key == null) return {};
			var r = key["Enum"];
			return r;
		},
		enumLanTxt(txt) {
			var lan = this.enumLan;
			if (lan == null) return txt;
			var r = lan[txt];
			if (r == null) return txt;
			return r;
		},
		init() {
			//console.log("common.js的init方法", this.$route.path);
		},
		beforeDestroy() {
			//console.log("common.js beforeDestroy");
			if (!!this.componentTag) {
				window[this.routePath + "/" + this.componentTag] = undefined;
				delete window[this.routePath + "/" + this.componentTag];
			} else {
				window[this.routePath] = undefined;
				delete window[this.routePath];
			}
		},

		commonUrl(url) {
			return tool.commonUrl(url);
		},
		getLabel(val, row, value, label, withColor) {
			if (withColor == null) withColor = true;
			if (val == null) return "";
			if (row == null) return "";
			if (value == null || value == "") value = "Value";
			if (label == null || label == "") label = "Label";
			for (let i = 0; i < row.length; i++) {
				let item = row[i];
				if ((item == null && item[value] == null) ||
					(item[value] != null && val.toString() == item[value].toString())) {
					let r = item[label];
					if (!!r) {
						r = this.enumLanTxt(r);
					}
					if (withColor) {
						let color = item["color"];
						if (color == null || color == "") color = item["Color"];
						if (color == null || color == "") return r;
						return "<font style='color:" + color + "'>" + r + "</font>";
					} else {
						return r;
					}
				}
			}
			return "";
			//return tool.getLabel(val, row, value, label, withColor);
		},
		colorRgb(val) {
			return tool.colorRgb(val);
		},
		toDate(val) {
			return tool.toDate(val);
		},
		format(val, format) {
			return tool.format(val, format);
		},
		toFixed(value, toFixed, pre, fix) {
			return tool.toFixed(value, toFixed, pre, fix);
		},

		get(url) {
			return tool.get(url);
		},
		post(url, data) {
			return tool.post(url, data);
		},
		ajax(op) {
			return tool.ajax(op);
		},

		showMsg(options, success) {
			return showMsg(options, success);
		},
		showToast(options, type) {
			return showToast(options, type);
		},
		confirm(options, success) {
			return confirm(options, success);
		},
		prompt(options) {
			return prompt(options);
		},

		navigateTo(url, queryObj) {
			return tool.navigateTo(url, queryObj);
		},
		navigateToRefresh(url, queryObj) {
			return tool.navigateToRefresh(url, queryObj);
		},
		closeCurrentPage() {
			//关闭当前
			var path = this.$route.fullPath;
			const views = this.$store.state.tabsBar.visitedRoutes.filter((item, index) => {
				if (item.fullPath === path) {
					return item;
				}
			});
			if (views == null || views.length == 0) return;
			var view = views[0];
			this.$store.dispatch("delRoute", view);
		},
		refreshList(url, queryObj, closeCurrentPage) {
			if (closeCurrentPage === undefined) closeCurrentPage = true;
			if (closeCurrentPage) {
				this.closeCurrentPage();
			}
			//list列表存在则调用getList,不存在则新开
			this.navigateToRefresh(url, queryObj);
		},
		navigateBack() {
			history.back();
		},
		getQuery() {
			let query = this.$route.query;
			return query;
		},
		toKeyValue(obj) {
			return tool.toKeyValue(obj);
		},
		toModel(obj) {
			return tool.toModel(obj);
		},
		Empty(obj) {
			return tool.Empty(obj);
		},
		getNumber(obj) {
			return tool.getNumber(obj);
		},
		goAnchor(selector) {
			return tool.goAnchor(selector);
		},
		//某个vm的表单是否通过验证,cbWhenSuccess,cbWhenError用于异步验证
		formValidate(formName, cbWhenSuccess, cbWhenError) {
			this.$refs[formName].validate(
				function (valid) {
					if (valid) {
						if (!!cbWhenSuccess) {
							cbWhenSuccess();
						}
					} else {
						if (!!cbWhenError) {
							cbWhenError();
						}
					}
				}
			);
		},
		resetThisVal(modelName) {
			this.resetVal(modelName);
			this.$nextTick(() => {
				this.clearBeforeVal();
			});
		},
		//重置某个值,此方法里的属性的data必须是一个function
		resetVal(keyName) {
			var hasKeyName = !!keyName;
			// var originalData = this.$options.data();
			var originalData = this.$options.data.call(this);
			var obj = hasKeyName ? originalData[keyName] : originalData;
			if (obj == null) {
				if (hasKeyName) {
					this[keyName] = null;
				}
				return;
			}
			var copy = JSON.parse(JSON.stringify(obj));
			if (hasKeyName) {
				this[keyName] = copy;
			} else {
				for (var item in copy) {
					this[item] = copy[item];
				}
			}
		},
		baseExportExcel(selector, fileName, param, success, fail) {
			return tool.baseExportExcel(selector, fileName, param, success, fail);
		},
		baseExportExcel2(selectorName, fileName, param, success, fail) {
			if (typeof (selectorName) !== "string") {
				this.showToast("参数错误,selector参数必须为ref的字符串值");
				return;
			}
			var ref = this.$refs[selectorName];
			if (ref == null) {
				this.showToast("未找到相关ref对象");
				return;
			}
			var beforeUseVirtual = this.useVirtual;
			var lan = config.getLanguageJs();
			var msg = tool.stringFormat(lan.exportString, fileName);
			var doCore = () => {
				/* 从表生成工作簿对象 */
				var selector = ref.$el;
				var obj = selector.querySelector(".el-table");
				var fix = obj.querySelector(".el-table__fixed-right"); //fix居右
				var fix2 = obj.querySelector('.el-table__fixed'); //fix居左或不设置
				var selection = obj.querySelector(".el-table-column--selection"); //前面的选择
				var bodySelections = obj.querySelector('table.el-table__body').querySelectorAll(
					".el-table-column--selection");

				var xlsxParam = {
					raw: true,
					display: true,
					removeColums: '操作'
				}; //转换成excel时，使用原始的格式
				xlsxParam = Object.assign(xlsxParam, param);

				var hideObjList = []; //需要隐藏的列
				var hideObjListDisplay = []; //隐藏列的display原来的值
				var hideIndex = [];

				var header = obj.querySelector('table.el-table__header');
				var body = obj.querySelector('table.el-table__body');
				var ths = header.querySelectorAll('th,td');
				//if (ths == null || ths.length == 0) continue;
				//不显示的列
				if (!!xlsxParam.removeColums && !!header && !!body && !!ths) {
					var rows = body.querySelectorAll(".el-table__row");
					if (rows != null && rows.length > 0) {
						var arr = xlsxParam.removeColums.split(',');
						for (var k = 0; k < arr.length; k++) {
							var colName = arr[k];
							var index;
							for (var l = 0; l < ths.length; l++) {
								var thItem = ths[l];
								var docDivTemp = document.createElement('div');
								//带fixed的不一样 他没有innserText的值,所以用一个临时变量div来存
								docDivTemp.innerHTML = thItem.innerHTML;
								if (docDivTemp.innerText.trim() == colName) {
									index = l;
									hideObjList.push(thItem);
									break;
								}
							}
							if (index != null) { //带fixed的不一样
								hideIndex.push(index);
								for (var l = 0; l < rows.length; l++) {
									var rowItem = rows[l];
									var hideTdObj = rowItem.querySelectorAll("td,th")[index];
									hideObjList.push(hideTdObj);
								}
							}
						}
					}
				}
				for (var i = 0; i < hideObjList.length; i++) {
					var item = hideObjList[i];
					var beforeDisplay = item.style.display;
					hideObjListDisplay.push(beforeDisplay);
					item.style.display = 'none';
				}
				var wb;
				//判断要导出的节点中是否有fixed的表格，如果有，转换excel时先将该dom移除，然后append回去
				if (!!fix) obj.removeChild(fix);
				if (!!fix2) obj.removeChild(fix2);
				var beforeDisplay;
				if (!!selection) {
					beforeDisplay = selection.style.display;
					selection.style.display = 'none';
					for (var m = 0; m < bodySelections.length; m++) {
						var s = bodySelections[m];
						s.style.display = 'none';
					}
				}
				wb = XLSX.utils.table_to_book(obj, xlsxParam);
				if (!!fix) obj.appendChild(fix);
				if (!!fix2) obj.appendChild(fix2);
				if (!!selection) {
					selection.style.display = beforeDisplay;
					for (var m = 0; m < bodySelections.length; m++) {
						var s = bodySelections[m];
						s.style.display = beforeDisplay;
					}
				}
				for (var i = 0; i < hideObjList.length; i++) {
					var item = hideObjList[i];
					item.style.display = hideObjListDisplay[i];
				}

				var sheet1 = wb.Sheets.Sheet1;
				//整理下宽度
				var colsArr = [];
				var dealFirst = true; //是否处理过第一条
				for (var n = 0; n < ths.length; n++) {
					if (this.arrContains(hideIndex, n)) continue;
					var thItem2 = ths[n];
					var widthTemp = parseInt(parseInt(thItem2.clientWidth.toString().replace('px', '')) /
						7.7);
					if (widthTemp <= 0) continue;
					if (dealFirst) {
						dealFirst = false;
						if (widthTemp < 20) widthTemp = 20;
					}
					if (thItem2.colSpan > 1) {
						var widthTemp2 = parseInt(widthTemp / thItem2.colSpan);
						for (var i = 0; i < thItem2.colSpan; i++) {
							colsArr.push({
								'wch': widthTemp2
							});
						}
					} else {
						colsArr.push({
							'wch': widthTemp
						});
					}
				}
				sheet1["!cols"] = colsArr;
				var letters = [
					"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q",
					"R", "S", "T",
					"U", "V", "W", "X", "Y", "Z",

					"AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH", "AI", "AJ", "AK", "AL", "AM", "AN",
					"AO", "AP", "AQ", "AR", "AS", "AT", "AU", "AV", "AW", "AX", "AY", "AZ"
				];
				var sCss = { //设置副标题样式
					font: {
						name: '宋体',
						//sz: 14,
						color: {
							rgb: "FFFFFF"
						},
						bold: true,
						italic: false,
						underline: false
					},
					alignment: {
						horizontal: "center",
						vertical: "center"
					},
					fill: {
						fgColor: {
							rgb: "A5A5A5"
						}
					}
				};
				for (var j = 0; j < letters.length; j++) {
					//第一行加粗或没有第一行,就第二行加样式
					var objTemp = sheet1[letters[j] + "1"];
					if (objTemp == null) {
						objTemp = sheet1[letters[j] + "2"];
						if (objTemp == null) {
							objTemp = sheet1[letters[j] + "3"];
							if (objTemp == null) {
								continue;
							} else {
								var objTemp3 = sheet1[letters[j - 1] + "3"];
								objTemp3.s = sCss;
							}
						} else {
							var objTemp2 = sheet1[letters[j - 1] + "2"];
							objTemp2.s = sCss;
						}
					}
					objTemp.s = sCss;
				}
				// return;
				/* 获取二进制字符串作为输出 */
				var wbout = XLSX.write(wb, {
					bookType: "xlsx",
					bookSST: true,
					type: "array"
				});
				var fullName = fileName + "_" +
					this.format(new Date(), 'yyyyMMddHHmmss') +
					"_" +
					(Math.random() * 10000).toString().substr(0, 5);
				try {
					var blob = new Blob([wbout], {
						type: "application/octet-stream"
					});
					saveAs(
						//Blob 对象表示一个不可变、原始数据的类文件对象。
						//Blob 表示的不一定是JavaScript原生格式的数据。
						//File 接口基于Blob，继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
						//返回一个新创建的 Blob 对象，其内容由参数中给定的数组串联组成。
						blob,
						//设置导出文件名称
						(fullName + ".xlsx")
					);
				} catch (e) {
					if (typeof console !== "undefined") console.log(e, wbout);
				}
				if (!!success) success();
				return wbout;
			};
			var doCoreF = () => {
				this.showToast(lan.exportStringManyRow); //"如果数据过多,会很慢,请稍后;导出中..."
				setTimeout(() => {
					try {
						this.useVirtual = false;
					} catch (e) { }
					this.$nextTick(() => {
						doCore();
						this.useVirtual = beforeUseVirtual;
						ref.$forceUpdate();
						this.showToast(lan.exportStringSuccess,
							"success"); //"导出成功,如果表格样式乱了,请刷新页面"
					});
				}, 500);
			};
			var options = {
				message: msg,
				success: () => {
					doCoreF();
				},
				fail: () => {
					if (!!fail) fail();
				}
			}
			confirm(options);
		},

		consoleLog() {
			tool.consoleLog.apply(tool, arguments);
		},
		stringFormat() {
			return tool.stringFormat.apply(tool, arguments);
		},
		windowOpen(args) {
			var url = tool.commonUrl(args);
			window.open(url);
		},
		arrContains(arr, obj, key) {
			return tool.arrContains(arr, obj, key);
		},
		blurNum(e, defaultVal) {
			if (e != null && e.target != null) {
				var isNull = e.target.value == null || e.target.value == 0;
				if (isNull) {
					if (defaultVal == null) defaultVal = 0;
					e.target.value = defaultVal;
				}
			}
		},

		//码畜辅助方法
		checkCsharp() {
			if (window.csharp == null) {
				this.showToast("请在码畜中打开", "error");
				return false;
			}
			return true;
		},
		csharp() {
			var args = Array.prototype.slice.call(arguments);
			var methodName = args[0];
			if (methodName.length > 1) {
				methodName = methodName.substr(0, 1).toLowerCase() + methodName.substr(1, methodName
					.length - 1);
			}
			var toast = this.showToast({
				message: "执行" + methodName + "中...",
				type: 'warning',
				showClose: true,
				duration: 0
			});
			var promise = new Promise((resolve, reject) => {
				if (this.checkCsharp() == false) {
					toast.close();
					reject();
					return;
				}
				var method = window.csharp[methodName];
				if (method == null) {
					toast.close();
					this.showToast("未找到相关方法,请核查", "error");
					reject();
					return;
				}
				args.splice(0, 1);
				method.apply(window.csharp, args).then(data => {
					toast.close();
					resolve(data);
				}).catch(error => {
					toast.close();
					this.showToast("执行报错:" + error, "error");
					reject(error);
				});
			});
			return promise;
		},

		getTemplateTypeAll() {
			return "0,1,2,3,4,5,6,20,21,22,23,24,25,26,27,28,29,30";
		},
		getTemplateTypeByProject(type) {
			//EnumDevProjectType PC后台WebApi = 100000
			if (type == 100000) {
				return "0,1,2,3,4,5,6";
			}
			if (type == 300000) {
				return "20,21,22,23,24,25,26,27,28,29,30";
			}
			return "0";
		}
	}
};

const showMsg = function (options, success) {
	var lan = config.getLanguageJs();
	if (options === null || options === undefined) options = "";
	if (typeof (options) == "string") {
		var temp = getApp().$alert(options, lan.tips, {
			confirmButtonText: lan.ok,
			callback: action => {
				if (!!success) success();
			}
		});
		return temp;
	}
	if (options.title == null) options.title = lan.tips;
	if (options.confirmButtonText == null) options.confirmButtonText = lan.ok;
	if (options.success != null) options.callback = options.success;

	var temp2 = getApp().$alert(options.message, options.title, {
		confirmButtonText: options.confirmButtonText,
		callback: action => {
			if (!!options.callback) options.callback(action);
		}
	});
	return temp2;
}

const showToast = function (options, type) {
	if (options === null || options === undefined) options = "";
	var duration = 5000;
	if (typeof (options) == "string") {
		var temp = getApp().$message({
			dangerouslyUseHTMLString: true,
			message: options,
			type: !!type ? type : 'warning',
			showClose: true,
			duration: duration
		});
		return temp;
	}
	if (options.showClose == null) {
		options.showClose = true;
	}
	if (options.duration == null) {
		options.duration = duration;
	}
	if (options.dangerouslyUseHTMLString == null) {
		options.dangerouslyUseHTMLString = true;
	}

	var temp2 = getApp().$message(options);
	return temp2;
}

const confirm = function (options, success, type) {
	var lan = config.getLanguageJs();
	if (options === null || options === undefined) options = "";
	if (typeof options == "string") {
		var op = {
			confirmButtonText: lan.ok,
			cancelButtonText: lan.cancel,
			type: !!type ? type : "warning",
			callback: (action) => {
				if (action == 'confirm') {
					if (!!success) success();
				}
				// else {
				//     if (!!options.fail) options.fail();
				// }
			}
		}
		getApp().$confirm(options, lan.tips, op);
		return;
	}
	if (options.title == null) options.title = lan.tips;
	if (options.confirmButtonText == null) options.confirmButtonText = lan.ok;
	if (options.cancelButtonText == null) options.cancelButtonText = lan.cancel;
	if (options.type == null) options.type = "warning";

	getApp().$confirm(options.message, options.title, {
		confirmButtonText: options.confirmButtonText,
		cancelButtonText: options.cancelButtonText,
		type: options.type,
		callback: (action) => {
			if (action == 'confirm') {
				if (!!options.success) options.success();
			} else {
				if (!!options.fail) options.fail();
			}
		}
	});
}

const prompt = function (options) {
	var lan = config.getLanguageJs();
	if (options.title == null) options.title = lan.tips;
	if (options.confirmButtonText == null) options.confirmButtonText = lan.ok;
	if (options.cancelButtonText == null) options.cancelButtonText = lan.cancel;
	if (options.showCancelButton == null) options.showCancelButton = true;
	if (options.inputValue == null) options.inputValue = "";
	getApp().$prompt(options.message, options.title, options).then((valObj) => {
		//输入的值valObj.value
		if (valObj.action == "confirm") {
			if (!!options.success) options.success(valObj.value);
		} else {
			if (!!options.fail) options.fail();
		}
	}).catch(() => {
		//取消输入
		if (!!options.fail) options.fail();
	});
}

function clipboardSuccess() {
	var lan = config.getLanguageJs();
	showToast(lan.opSuccess, 'success')
}

function clipboardError() {
	var lan = config.getLanguageJs();
	showToast(lan.opFail, 'error')
}

//其它工具类
const tool = {
	navigateTo(url, queryObj) {
		getApp().$router.push({
			path: url,
			query: queryObj
		});
	},
	navigateToRefresh(url, queryObj) {
		getApp().$router.push({
			path: url,
			query: queryObj
		});
		//新开的页面,下面的值为null
		var appTemp = window[url];
		if (appTemp != null && appTemp.init != null) {
			appTemp.init();
		}
	},
	ajax(op) {
		//处理一下参数
		let token = store.state.user.token;
		let lang = store.state.lang;
		//console.log("token", token);
		let options = {
			headers: {
				'Content-Type': 'application/json; charset=utf-8'
			},
			timeout: 20000
		};
		if (!!token) {
			options.headers[config.tokenKey] = token;
		}
		let wechatToken = getWechatToken();
		if (!!wechatToken) {
			options.headers[config.wechatTokenKey] = wechatToken;
		}
		if (!!lang) {
			options.headers["lang"] = lang;
		}
		var device = getDeviceId();
		if (!!device) {
			options.headers["deviceid"] = device;
		}
		op.url = this.commonUrl(op.url);
		options = Object.assign(options, op);
		//返回一个promise对象
		return new Promise((resolve, reject) => {
			let promise;
			if (options.method.toUpperCase() === 'GET') { // get请求
				promise = axios.get(options.url, options);
			} else { // post请求
				promise = axios.post(options.url, options.data, options);
			}
			//处理结果并返回
			promise.then((response) => {
				var data = response.data;
				var tempReturn = config.commonAjaxSuccess(data);
				if (tempReturn == false) {
					reject(data);
					return;
				}
				resolve(data);
			}).catch(error => {
				var lan = config.getLanguageJs();
				console.log(lan.ajaxError, error);
				error = lan[error] || error;
				showToast(lan.ajaxError + error);
				reject(error);
			})
		});
	},
	get(url) {
		return this.ajax({
			url: url,
			method: "GET"
		});
	},
	post(url, data) {
		return this.ajax({
			url: url,
			method: "POST",
			data: data
		});
	},
	commonUrl(url) {
		if (url == null || url == '') {
			return url;
		}
		if (url.indexOf("data:") == 0) {
			return url;
		}
		if (url.indexOf('http://') == -1 && url.indexOf('https://') == -1) {
			var r = config.webapiUrl + (url.indexOf('/') != 0 ? '/' : '') + url;
			return r;
		}
		return url;
	},
	toKeyValue(obj) {
		// if (searchName == null || searchName == "") searchName = "search";
		// var result = new FormData();
		// for (var item in obj) {
		//     var json = {
		//         "key": item,
		//         "value": obj[item]
		//     };
		//     //console.log(item, obj[item], JSON.stringify(json));
		//     result.append(searchName, JSON.stringify(json));
		// }
		// return result;
		var result = new FormData();
		for (var item in obj) {
			var val = obj[item];
			if (val == null) continue;
			if (val instanceof Array && val.length == 0) continue;
			result.append(item, val);
		}
		return result;
	},
	getLabel(val, row, value, label, withColor) {
		if (withColor == null) withColor = true;
		if (val == null) return "";
		if (row == null) return "";
		if (value == null || value == "") value = "Value";
		if (label == null || label == "") label = "Label";
		for (let i = 0; i < row.length; i++) {
			let item = row[i];
			if ((item == null && item[value] == null) ||
				(item[value] != null && val.toString() == item[value].toString())) {
				let r = item[label];
				if (withColor) {
					let color = item["color"];
					if (color == null || color == "") color = item["Color"];
					if (color == null || color == "") return r;
					return "<font style='color:" + color + "'>" + r + "</font>";
				} else {
					return r;
				}
			}
		}
		return "";
	},
	dateStringReplace(val) {
		if (val == null || val == '') return '';
		var r = val.replace(/-/g, '/');
		r = r.replace(/T/, ' ').replace(/Z/, '');
		return r;
	},
	toDate(val) {
		if (typeof (val) != "string") return val;
		try {
			val = this.dateStringReplace(val);
			if (val == '') return '';
			let time = new Date(val);
			return time;
		} catch (e) {
			return '';
		}
	},
	format(val, format) {
		if (!val) return '';
		if (!format) format = 'yyyy-MM-dd HH:mm:ss';
		format = format.replace(/HH/g, 'hh');
		let time = tool.toDate(val);
		if (time == '') return '';
		let o = {
			"M+": time.getMonth() + 1, //月份
			"d+": time.getDate(), //日
			"h+": time.getHours(), //小时
			"m+": time.getMinutes(), //分
			"s+": time.getSeconds(), //秒
			"q+": Math.floor((time.getMonth() + 3) / 3), //季度
			"S": time.getMilliseconds() //毫秒
		};
		if (/(y+)/.test(format)) format = format.replace(RegExp.$1, (time.getFullYear() + "").substr(4 -
			RegExp.$1.length));
		for (let k in o)
			if (new RegExp("(" + k + ")").test(format))
				format = format.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(
					("" + o[k]).length)));
		if (format == "NaN-aN-aN" || format == "NaN-Na-Na" || format == "NaN-NaN-NaN") {
			return '';
		}
		return format;
	},
	toFixed(value, toFixed, pre, fix) {
		if (toFixed == null) toFixed = 2;
		pre = pre || '';
		value = parseFloat(value) || 0;
		fix = fix || '';
		return (pre + value.toFixed(toFixed) + fix);
	},
	goAnchor(selector) {
		var $anchor = $(selector); //获取元素
		if ($anchor == null || $anchor == undefined) return;
		//$anchor.scrollIntoView(); //js的内置方法，可滚动视图位置至元素位置
		var targetOffset = $anchor.offset().top;
		//console.info("targetOffset", targetOffset)
		$('html,body').animate({
			scrollTop: targetOffset
		}, 500);
	},
	pad(num, n) {
		var len = num.toString().length;
		while (len < n) {
			num = "0" + num;
			len++;
		}
		return num;
	},
	/*生成指定长度的随机数*/
	randomCode(length) {
		if (length == null) length = 5;
		let chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
		let result = "";
		for (let i = 0; i < length; i++) {
			let index = Math.ceil(Math.random() * 9);
			result += chars[index];
		}
		return result;
	},
	// 本地化存储
	setStore(name, val) {
		if (!name) return;
		if (!val) {
			window.sessionStorage.removeItem(name);
			return;
		}
		if (typeof val !== 'string') {
			val = JSON.stringify(val);
		}
		try {
			window.sessionStorage.setItem(name, val);
		} catch (e) { }
	},
	// 本地化获取
	getStore(name) {
		if (!name) return
		return window.sessionStorage.getItem(name)
	},
	// 本地化删除
	removeStore(name) {
		if (!name) return
		return window.sessionStorage.removeItem(name)
	},
	// 本地化存储
	setItem(name, val) {
		if (!name) return;
		if (!val) {
			window.localStorage.removeItem(name);
			return;
		}
		if (typeof val !== 'string') {
			val = JSON.stringify(val)
		}
		try {
			window.localStorage.setItem(name, val);
		} catch (e) { }
	},
	// 本地化获取
	getItem(name) {
		if (!name) return
		return window.localStorage.getItem(name)
	},
	// 本地化删除
	removeItem(name) {
		if (!name) return
		return window.localStorage.removeItem(name)
	},
	getCookie(cname) {
		var r = cookie.get(cname);
		return r;
	},
	setCookie(cname, cvalue, exmins) {
		if (!cvalue) {
			cookie.remove(cname);
			return;
		}
		if (exmins == null) exmins = 0; //cookie有效期为session会话结束
		cookie.set(cname, cvalue, exmins);
	},
	//验证车牌码的正则表达式
	checkCarNumber(CarNumber) {
		var result = false;
		if (CarNumber.length == 7) {
			var express =
				/^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领]{1}[A-Za-z]{1}[A-Za-z0-9]{4}[A-Za-z0-9挂学警港澳]{1}$/;
			result = express.test(CarNumber);
		} else if (CarNumber.length == 8) {
			var express =
				/^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领]{1}[A-Za-z]{1}[A-Za-z0-9]{5}[A-Za-z0-9挂学警港澳]{1}$/;
			result = express.test(CarNumber);
		}
		return result;
	},
	isPhone(val) {
		if (val == null || val == '') {
			return false;
		} else {
			if (!/^1(3|4|5|6|7|8|9)\d{9}$/.test(val)) {
				return false;
			}
		}
		return true;
	},
	arrContains(arr, obj, key) {
		if (arr == null || arr.length == 0) return false;
		let hasKey = key != null && key != "";
		for (let i = 0; i < arr.length; i++) {
			if (hasKey) {
				if (obj[key] == arr[i][key]) {
					return true;
				}
			} else {
				if (obj == arr[i]) {
					return true;
				}
			}
		}
		return false;
	},
	//定义导出Excel表格事件 //baseExportExcel('#tblList', '商家信息',{removeColums:'操作,签约人,管理人'})
	baseExportExcel(selector, fileName, param, success, fail, init) {
		var lan = config.getLanguageJs();
		var msg;
		if (init == null) msg = this.stringFormat(lan.exportString, fileName);
		else msg = this.stringFormat(lan.exportString2, fileName);
		var doCore = () => {
			/* 从表生成工作簿对象 */
			var obj = typeof (selector) == "string" ? document.querySelector(selector) : selector;
			var fix = obj.querySelector(".el-table__fixed-right"); //fix居右
			var fix2 = obj.querySelector('.el-table__fixed'); //fix居左或不设置
			var selection = obj.querySelector(".el-table-column--selection"); //前面的选择
			var bodySelections = obj.querySelector('table.el-table__body').querySelectorAll(
				".el-table-column--selection");

			var xlsxParam = {
				raw: true,
				display: true,
				removeColums: lan.operation
			}; //转换成excel时，使用原始的格式
			xlsxParam = Object.assign(xlsxParam, param);

			var hideObjList = []; //需要隐藏的列
			var hideObjListDisplay = []; //隐藏列的display原来的值
			var hideIndex = [];

			var header = obj.querySelector('table.el-table__header');
			var body = obj.querySelector('table.el-table__body');
			var ths = header.querySelectorAll('th,td');
			//if (ths == null || ths.length == 0) continue;
			//不显示的列
			if (!!xlsxParam.removeColums && !!header && !!body && !!ths) {
				var rows = body.querySelectorAll(".el-table__row");
				if (rows != null && rows.length > 0) {
					var arr = xlsxParam.removeColums.split(',');
					for (var k = 0; k < arr.length; k++) {
						var colName = arr[k];
						var index;
						for (var l = 0; l < ths.length; l++) {
							var thItem = ths[l];
							var docDivTemp = document.createElement('div');
							//带fixed的不一样 他没有innserText的值,所以用一个临时变量div来存
							docDivTemp.innerHTML = thItem.innerHTML;
							if (docDivTemp.innerText.trim() == colName) {
								index = l;
								hideObjList.push(thItem);
								break;
							}
						}
						if (index != null) { //带fixed的不一样
							hideIndex.push(index);
							for (var l = 0; l < rows.length; l++) {
								var rowItem = rows[l];
								var hideTdObj = rowItem.querySelectorAll("td,th")[index];
								hideObjList.push(hideTdObj);
							}
						}
					}
				}
			}
			for (var i = 0; i < hideObjList.length; i++) {
				var item = hideObjList[i];
				var beforeDisplay = item.style.display;
				hideObjListDisplay.push(beforeDisplay);
				item.style.display = 'none';
			}
			var wb;
			//判断要导出的节点中是否有fixed的表格，如果有，转换excel时先将该dom移除，然后append回去
			if (!!fix) obj.removeChild(fix);
			if (!!fix2) obj.removeChild(fix2);
			var beforeDisplay;
			if (!!selection) {
				beforeDisplay = selection.style.display;
				selection.style.display = 'none';
				for (var m = 0; m < bodySelections.length; m++) {
					var s = bodySelections[m];
					s.style.display = 'none';
				}
			}
			wb = XLSX.utils.table_to_book(obj, xlsxParam);
			if (!!fix) obj.appendChild(fix);
			if (!!fix2) obj.appendChild(fix2);
			if (!!selection) {
				selection.style.display = beforeDisplay;
				for (var m = 0; m < bodySelections.length; m++) {
					var s = bodySelections[m];
					s.style.display = beforeDisplay;
				}
			}
			for (var i = 0; i < hideObjList.length; i++) {
				var item = hideObjList[i];
				item.style.display = hideObjListDisplay[i];
			}

			var sheet1 = wb.Sheets.Sheet1;
			//整理下宽度
			var colsArr = [];
			var dealFirst = true; //是否处理过第一条
			for (var n = 0; n < ths.length; n++) {
				if (this.arrContains(hideIndex, n)) continue;
				var thItem2 = ths[n];
				var widthTemp = parseInt(parseInt(thItem2.clientWidth.toString().replace('px', '')) /
					7.7);
				if (widthTemp <= 0) continue;
				if (dealFirst) {
					dealFirst = false;
					if (widthTemp < 20) widthTemp = 20;
				}
				if (thItem2.colSpan > 1) {
					var widthTemp2 = parseInt(widthTemp / thItem2.colSpan);
					for (var i = 0; i < thItem2.colSpan; i++) {
						colsArr.push({
							'wch': widthTemp2
						});
					}
				} else {
					colsArr.push({
						'wch': widthTemp
					});
				}
			}
			sheet1["!cols"] = colsArr;
			var letters = [
				"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q",
				"R", "S", "T",
				"U", "V", "W", "X", "Y", "Z",

				"AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH", "AI", "AJ", "AK", "AL", "AM", "AN",
				"AO", "AP", "AQ", "AR", "AS", "AT", "AU", "AV", "AW", "AX", "AY", "AZ"
			];
			var sCss = { //设置副标题样式
				font: {
					name: '宋体',
					//sz: 14,
					color: {
						rgb: "FFFFFF"
					},
					bold: true,
					italic: false,
					underline: false
				},
				alignment: {
					horizontal: "center",
					vertical: "center"
				},
				fill: {
					fgColor: {
						rgb: "A5A5A5"
					}
				}
			};
			for (var j = 0; j < letters.length; j++) {
				//第一行加粗或没有第一行,就第二行加样式
				var objTemp = sheet1[letters[j] + "1"];
				if (objTemp == null) {
					objTemp = sheet1[letters[j] + "2"];
					if (objTemp == null) {
						objTemp = sheet1[letters[j] + "3"];
						if (objTemp == null) {
							continue;
						} else {
							var objTemp3 = sheet1[letters[j - 1] + "3"];
							objTemp3.s = sCss;
						}
					} else {
						var objTemp2 = sheet1[letters[j - 1] + "2"];
						objTemp2.s = sCss;
					}
				}
				objTemp.s = sCss;
			}
			// return;
			/* 获取二进制字符串作为输出 */
			var wbout = XLSX.write(wb, {
				bookType: "xlsx",
				bookSST: true,
				type: "array"
			});
			var fullName = fileName + "_" +
				this.format(new Date(), 'yyyyMMddHHmmss') +
				"_" +
				(Math.random() * 10000).toString().substr(0, 5);
			try {
				var blob = new Blob([wbout], {
					type: "application/octet-stream"
				});
				saveAs(
					//Blob 对象表示一个不可变、原始数据的类文件对象。
					//Blob 表示的不一定是JavaScript原生格式的数据。
					//File 接口基于Blob，继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
					//返回一个新创建的 Blob 对象，其内容由参数中给定的数组串联组成。
					blob,
					//设置导出文件名称
					(fullName + ".xlsx")
				);
			} catch (e) {
				if (typeof console !== "undefined") console.log(e, wbout);
			}
			if (!!success) success();
			return wbout;
		};
		var options = {
			message: msg,
			success: () => {
				if (init == null) {
					doCore();
				} else {
					init(doCore);
				}
			},
			fail: () => {
				if (!!fail) fail();
			}
		}
		confirm(options);
	},
	makePy(character, val) { //需引入Mtils.min.js
		if (window.Mtils != null) {
			if (character.indexOf(val) > -1) {
				return true;
			}
			var py = Mtils.utils.makePy(character).toLowerCase(); //全拼音
			if (py.indexOf(val) > -1) {
				return true;
			}
			py = Mtils.utils.makePy(character, true).toLowerCase(); //只取汉字首字母拼音
			if (py.indexOf(val) > -1) {
				return true;
			}
			return false;
		}
		return false;
	},
	getPy(character) { //简拼加全拼
		if (window.Mtils != null) {
			return Mtils.utils.makePy(character).toUpperCase() + "|" + Mtils.utils.makePy(character, true)
				.toUpperCase();
		}
		return '';
	},

	//国标转成百度坐标 需引入coordtransform.js
	wgs84tobd09(longitude, latitude) {
		var temp = coordtransform.wgs84togcj02(longitude, latitude);
		var r = coordtransform.gcj02tobd09(temp[0], temp[1]);
		return r; //返回[longitude, latitude]
	},
	//百度坐标转成国标
	bd09towgs84(longitude, latitude) {
		var temp = coordtransform.bd09togcj02(longitude, latitude);
		var r = coordtransform.gcj02towgs84(temp[0], temp[1]);
		return r; //返回[longitude, latitude]
	},
	//百度坐标转成火星坐标(高德和腾讯)
	bd09togcj02(longitude, latitude) {
		var temp = coordtransform.bd09togcj02(longitude, latitude);
		return temp; //返回[longitude, latitude]
	},
	//火星坐标(高德和腾讯)转成百度坐标
	gcj02tobd09(longitude, latitude) {
		var temp = coordtransform.gcj02tobd09(longitude, latitude);
		return temp; //返回[longitude, latitude]
	},
	//md5.hexMD5(self.pwd).toUpperCase() MD5.JS

	//判读是否为外链
	isExternal(path) {
		return /^(https?:|mailto:|tel:)/.test(path)
	},
	//校验密码
	isPassword(str) {
		return str.length >= 6
	},
	//判断是否为数字
	isNumber(value) {
		const reg = /^[0-9]*$/
		return reg.test(value)
	},
	//判断是否是名称
	isName(value) {
		const reg = /^[\u4e00-\u9fa5a-zA-Z0-9]+$/
		return reg.test(value)
	},
	//是否是IP地址
	isIP(ip) {
		const reg =
			/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
		return reg.test(ip)
	},
	//判断是否是传统网站
	isUrl(url) {
		const reg =
			/^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
		return reg.test(url)
	},
	//判断是否是小写字母
	isLowerCase(str) {
		const reg = /^[a-z]+$/
		return reg.test(str)
	},
	//判断是否是大写字母
	isUpperCase(str) {
		const reg = /^[A-Z]+$/
		return reg.test(str)
	},
	//判断是否是大写字母开头
	isAlphabets(str) {
		const reg = /^[A-Za-z]+$/
		return reg.test(str)
	},
	//判断是否是身份证号(第二代)
	isIdCard(str) {
		const reg = /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
		return reg.test(str)
	},
	//判断是否是邮箱
	isEmail(str) {
		const reg = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/
		return reg.test(str)
	},
	//判断是否中文
	isChina(str) {
		const reg = /^[\u4E00-\u9FA5]{2,4}$/
		return reg.test(str)
	},
	//判断是否为空
	isBlank(str) {
		return (
			str == null ||
			false ||
			str === '' ||
			str.trim() === '' ||
			str.toLocaleLowerCase().trim() === 'null'
		)
	},
	//判断是否为固话
	isTel(str) {
		const reg = /^(400|800)([0-9\\-]{7,10})|(([0-9]{4}|[0-9]{3})(-| )?)?([0-9]{7,8})((-| |转)*([0-9]{1,4}))?$/
		return reg.test(str)
	},
	//判断是否为数字且最多两位小数
	isNum(str) {
		const reg = /^\d+(\.\d{1,2})?$/
		return reg.test(str)
	},
	//全局TableHeight
	baseTableHeight(formType) {
		let height = window.innerHeight;
		//与/src/css/variables.scss的$base-padding有关,左右上下滚动条会出现的问题
		let paddingHeight = 365; //500
		const formHeight = 50;
		let layout = store.state.theme.layout;
		if (layout === 'vertical') {
			paddingHeight = 365 + 25; // 365
		}
		if ('number' == typeof formType) {
			height = height - paddingHeight - formHeight * formType;
		} else {
			height = height - paddingHeight;
		}
		if (height <= 250) height = 250;
		return height;
	},
	baseTableHeight2(formType) {
		let height = window.innerHeight
		let paddingHeight = 225; //500
		const formHeight = 50;
		let layout = store.state.theme.layout;
		if (layout === 'vertical') {
			paddingHeight = 225 + 25; // 365
		}
		if ('number' == typeof formType) {
			height = height - paddingHeight - formHeight * formType;
		} else {
			height = height - paddingHeight;
		}
		if (height <= 250) height = 250;
		return height;
	},
	baseNotify(message, title, type, position) {
		Notification({
			title: title,
			message: message,
			position: position || 'top-right',
			type: type || 'success',
			duration: 0,
		});
	},
	handleIsMobile() {
		return document.body.getBoundingClientRect().width - 1 < 992;
	},
	clip(text, event) {
		const clipboard = new Clipboard(event.target, {
			text: () => text,
		})
		clipboard.on('success', () => {
			clipboardSuccess()
			clipboard.destroy()
		})
		clipboard.on('error', () => {
			clipboardError()
			clipboard.destroy()
		})
		clipboard.onClick(event)
	},
	md5(str) {
		var r = md5(str);
		return r;
	},
	stringFormat() {
		var s = arguments[0];
		for (var i = 0; i < arguments.length - 1; i++) {
			var reg = new RegExp("\\{" + i + "\\}", "gm");
			s = s.replace(reg, arguments[i + 1]);
		}
		return s;
	},
	consoleLog() {
		var args = Array.prototype.slice.call(arguments);
		console.log.apply(console, args);
	},
	randomNum(minNum, maxNum) {
		switch (arguments.length) {
			case 1:
				return parseInt(Math.random() * minNum + 1, 10);
				break;
			case 2:
				return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
				break;
			default:
				return 0;
				break;
		}
	},
	deepClone(target) {
		var hasOwnProperty = Object.prototype.hasOwnProperty;
		var propIsEnumerable = Object.prototype.propertyIsEnumerable;

		function isObj(x) {
			var type = typeof x;
			return x !== null && (type === 'object' || type === 'function');
		}

		function toObject(val) {
			if (val === null || val === undefined) {
				throw new TypeError('Cannot convert undefined or null to object');
			}
			return Object(val);
		}

		function assignKey(to, from, key) {
			var val = from[key];
			if (val === undefined || val === null) {
				return;
			}
			if (hasOwnProperty.call(to, key)) {
				if (to[key] === undefined || to[key] === null) {
					throw new TypeError('Cannot convert undefined or null to object (' + key + ')');
				}
			}
			if (!hasOwnProperty.call(to, key) || !isObj(val)) {
				to[key] = val;
			} else {
				to[key] = assign(Object(to[key]), from[key]);
			}
		}

		function assign(to, from) {
			if (to === from) {
				return to;
			}
			from = Object(from);
			for (var key in from) {
				if (hasOwnProperty.call(from, key)) {
					assignKey(to, from, key);
				}
			}
			if (Object.getOwnPropertySymbols) {
				var symbols = Object.getOwnPropertySymbols(from);

				for (var i = 0; i < symbols.length; i++) {
					if (propIsEnumerable.call(from, symbols[i])) {
						assignKey(to, from, symbols[i]);
					}
				}
			}
			return to;
		}

		target = toObject(target);
		for (var s = 1; s < arguments.length; s++) {
			assign(target, arguments[s]);
		}
		return target;
	}
};

const getToken = function () {
	if (config.tokenIsCookie) {
		let r = tool.getCookie(config.tokenKey);
		if (!r) {
			r = '';
		}
		r = decodeURIComponent(r);
		return r;
	} else {
		let r = tool.getItem(config.tokenKey);
		if (!r) {
			r = '';
		}
		r = decodeURIComponent(r);
		return r;
	}
}

const setToken = function (val) {
	if (typeof val != "string") {
		val = JSON.stringify(val);
	}
	val = encodeURIComponent(val);
	if (config.tokenIsCookie) {
		let r = tool.setCookie(config.tokenKey, val);
		if (!r) {
			r = '';
		}
		return r;
	} else {
		let r = tool.setItem(config.tokenKey, val);
		if (!r) {
			r = '';
		}
		return r;
	}
}

const getWechatToken = function () {
	if (config.tokenIsCookie) {
		let r = tool.getCookie(config.wechatTokenKey);
		if (!r) {
			r = '';
		}
		r = decodeURIComponent(r);
		return r;
	} else {
		let r = tool.getItem(config.wechatTokenKey);
		if (!r) {
			r = '';
		}
		r = decodeURIComponent(r);
		return r;
	}
}

const setWechatToken = function (val) {
	if (typeof val != "string") {
		val = JSON.stringify(val);
	}
	val = encodeURIComponent(val);
	if (config.tokenIsCookie) {
		let r = tool.setCookie(config.wechatTokenKey, val);
		if (!r) {
			r = '';
		}
		return r;
	} else {
		let r = tool.setItem(config.wechatTokenKey, val);
		if (!r) {
			r = '';
		}
		return r;
	}
}

const isWechat = function () {
	if (window == null || window.navigator == null) {
		return false;
	}
	return /MicroMessenger/i.test(window.navigator.userAgent);
}

const postAjaxError = function (e, other) {
	try {
		//设备类型
		var info = window.navigator.userAgent;
		var envPlatform = 'H5.isWechat:' + isWechat();
		var data = {
			info: info,
			envPlatform: envPlatform,
			other: 'url:' + location.href + ' ;' + other,
			error: !!e ? (!!e.stack ? e.stack : (e.toString() == "[object Object]" ? JSON.stringify(
				e) : e.toString())) : ""
		};
		var postData = tool.toKeyValue(data);
		if (config.ajaxErrorUrl == null || config.ajaxErrorUrl == "") {
			console.log("postAjaxError没有url,不提交JS", postData);
			return;
		}
		console.log("postAjaxError提交数据开始...", postData);
		tool.post(config.ajaxErrorUrl, postData);
	} catch (e) {
		console.log("postAjaxError中的e:", e);
	}
}

//报错机制记录
const recordError = function () {
	if (config.recordError) {
		window.Vue.config.errorHandler = (err, vm, info) => {
			try {
				var lan = config.getLanguageJs();
				console.log(lan.vueError, err, vm, info);
				if (!!config.errorAction) {
					window.Vue.nextTick(() => {
						store.dispatch(config.errorAction, {
							err,
							vm,
							info,
							url: window.location.href
						});
					});
				}
				postAjaxError(err, info);
			} catch (e) {
				console.log("common.recordError报错:", e);
			}
		};
	}
}

const initElementUI = function () {
	var lan = config.getLanguageJs();
	//ElementUI初始化
	var tempVueCom = Vue.component("ElTableColumn").options;
	tempVueCom.props.headerAlign.default = "center";
	tempVueCom.props.align.default = "center";
	tempVueCom.props.showOverflowTooltip.default = true;
	tempVueCom = Vue.component("ElTable").options;
	tempVueCom.props.highlightCurrentRow.default = true;
	tempVueCom.props.border.default = true;
	tempVueCom.props.tooltipEffect.default = "dark";
	tempVueCom.props.height.default = tool.baseTableHeight();

	//UTable
	tempVueCom = Vue.component("UTableColumn").options;
	tempVueCom.props.headerAlign.default = "center";
	tempVueCom.props.align.default = "center";
	tempVueCom.props.showOverflowTooltip.default = true;
	tempVueCom = Vue.component("UTable").options;
	tempVueCom.props.highlightCurrentRow.default = true;
	tempVueCom.props.border.default = true;
	tempVueCom.props.tooltipEffect.default = "dark";
	tempVueCom.props.height.default = tool.baseTableHeight();

	//tempVueCom.props.emptyText.default = "暂无数据";
	tempVueCom = Vue.component("ElButton").options;
	tempVueCom.props.type.default = "primary";
	//tempVueCom.props.size.default = "small";//写在全局里了
	tempVueCom = Vue.component("ElPagination").options;
	tempVueCom.props.background.default = true;
	tempVueCom.props.pageSizes.default = function () {
		return [10, 20, 50, 100, 200, 500, 1000, 2000];
	};
	tempVueCom.props.layout.default = "total, sizes, prev, pager, next, jumper";

	tempVueCom = Vue.component("ElInput").options;
	tempVueCom.props.clearable.default = true;
	//tempVueCom.props.size.default = "small";
	tempVueCom = Vue.component("ElDatePicker").options;
	tempVueCom.props.editable.default = false; //阻止手机端的时间控件弹出输入框
	//tempVueCom.props.size.default = "small";
	tempVueCom.props.placeholder.default = lan.choiceDate;
	//tempVueCom.props.type.default = "daterange";
	tempVueCom.props.pickerOptions.default = function () {
		return { //type="daterange"调用
			shortcuts: [{
				text: lan.lastWeek,
				onClick(picker) {
					var end = new Date();
					var start = new Date();
					start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
					picker.$emit('pick', [start, end]);
				}
			}, {
				text: lan.lastMonth,
				onClick(picker) {
					var end = new Date();
					var start = new Date();
					start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
					picker.$emit('pick', [start, end]);
				}
			}, {
				text: lan.last3Months,
				onClick(picker) {
					var end = new Date();
					var start = new Date();
					start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
					picker.$emit('pick', [start, end]);
				}
			}]
		};
	}
	tempVueCom = Vue.component("ElInputNumber").options;
	tempVueCom.props.controlsPosition.default = "right";
	tempVueCom = Vue.component("ElForm").options;
	tempVueCom.props.inline.default = true;
	tempVueCom = Vue.component("ElSelect").options;
	//tempVueCom.props.clearable.default = true;//为true手机端需要点击两次,而解决办法却是那种要弹出输入框的,所以不默认开启
	//tempVueCom.props.size.default = "small";
	tempVueCom.props.filterMethod.default = function (val) {
		if (val == null || val.trim() == "") {
			for (var i = 0; i < this.options.length; i++) {
				this.options[i].visible = true;
			}
			return;
		}
		val = val.trim();
		for (var i = 0; i < this.options.length; i++) {
			var item = this.options[i];
			var has = item.label.indexOf(val) != -1 || tool.getPy(item.label).toLowerCase().indexOf(val
				.toLowerCase()) != -1;
			if (has) {
				item.visible = true;
			} else {
				item.visible = false;
			}
		}
	}
	tempVueCom = Vue.component("ElDialog").options;
	tempVueCom.props.closeOnClickModal.default = false;
	//ckeditor的有BUG,appendToBody需要改为false
	//多个弹窗,自行设置appendToBody为true,不然弹窗遮罩层有BUG
	tempVueCom.props.appendToBody.default = false;
	tempVueCom.props.destroyOnClose.default = true;

	//手机版Dialog就没有
	if (tool.handleIsMobile()) {
		tempVueCom.props.top.default = "";
	}

	tempVueCom = Vue.component("ElCascader").options;
	tempVueCom.props.popperClass.default = "popperClass";

	Vue.filter('money', function (value, symbol) {
		if (symbol) {
			return symbol + Number(value).toFixed(2);
		}
		return '' + Number(value).toFixed(2);
	});

	Vue.filter('date', function (value) {
		if (value == null || value == '') {
			return '';
		}
		return tool.format(value, 'yyyy-MM-dd');
	});

	Vue.filter('datetime', function (value) {
		if (value == null || value == '') {
			return '';
		}
		return tool.format(value, '');
	});
}

//getApp()建立之前调用的
const init = function () {
	recordError();
	initElementUI();
}

const getApp = function () {
	return window.app;
}

const getDeviceId = function () {
	let deviceId = tool.getItem('uni_deviceId') || Math.random().toString(36).substr(2);
	tool.setItem('uni_deviceId', deviceId);
	return deviceId;
}

var setTimeoutGetTokenFromAjax = null;
var array = []; //ajax回调集合
const getTokenFromAjax = function (callback, noWaiting) {
	if (callback == null) return;
	for (var i = 0; i < array.length; i++) {
		if (array[i] == callback) {
			return;
		}
	}
	array.push(callback);

	var doNext = () => {
		getTokenFromAjaxBase((token) => {
			for (var j = 0; j < array.length; j++) {
				var fun = array[j];
				fun(token);
			}
			array = [];
			setTimeoutGetTokenFromAjax = null;
		});
	}

	if (noWaiting) {
		doNext();
		return;
	}

	if (setTimeoutGetTokenFromAjax != null) {
		return;
	}
	setTimeoutGetTokenFromAjax = setTimeout(() => {
		doNext();
	}, 500);
}

var loginSuccess = (data, callback) => {
	setWechatToken(data.Message);
	//加载登录信息
	if (!!data.Result && data.Result.length > 0) {
		var app = getApp();
		var comLan = app.$store.state.language;
		var temp = showToast(comLan[config.loginUrl].loginSuccess, "success");
		var info = data.Result[0];
		config.loginSetInfo(info);

		setTimeout(() => {
			if (temp != null) temp.close();
		}, 500);
	}
	if (!!callback) callback(data.Message);
}

function QueryString(val) {
	var url = window.location.href;
	if (url.indexOf('?') == -1) return "";
	var reg = new RegExp("(^|&)" + val + "=([^&]*)(&|$)", "i");
	var r = url.split('?')[1].match(reg);
	if (r != null) return decodeURIComponent(r[2]);
	return null;
};

//重新获取token,则先清除掉token
const getTokenFromAjaxBase = function (callback) {
	var isWechatResult = isWechat();
	if (isWechatResult == false) {
		if (!!callback) callback();
		return;
	}
	var wechatToken = getWechatToken();
	var h5FromCookie = config.wechatTokenKey + "FromCookie";
	var cookieToken = tool.getCookie(h5FromCookie);
	if (!!cookieToken) {
		cookieToken = decodeURIComponent(cookieToken);
		console.log("模拟登录的", cookieToken);
		setWechatToken(cookieToken);
		tool.setCookie(h5FromCookie, "");
		wechatToken = cookieToken;
	}

	if (!!wechatToken) {
		//path.indexOf("/dashboard/LuckyturningNew")
		if (!!callback) callback(wechatToken);
		return;
	}
	var isDev = process.env.NODE_ENV === 'development';
	if (isDev && isWechatResult) { //开发的时候
		var postTemp = tool.toKeyValue({
			openID: config.testOpenID,
			EnumOpenIDType: 0 //微信公众号
		});

		tool.post('api/Login/GetTestOpenID', postTemp).then((data) => {
			if (data.Success) {
				loginSuccess(data, callback);
				return;
			} else {
				showMsg('未获取到测试openid');
				return;
			}
		});
		return;
	}
	//跳转链接
	var code = QueryString("code");
	if (!!code) {
		var postData = tool.toKeyValue({
			code: code,
			EnumOpenIDType: 0
		});
		tool.post('/api/Login/GetOpenID', postData).then((data) => {
			if (data.Success) {
				loginSuccess(data, callback);

				function changeH5Url() {
					try {
						//修改Url
						var url = location.href;
						var arr = url.split('#');
						if (arr.length < 2) {
							return;
						}
						var first = arr[0];
						var index = first.indexOf('?');
						if (index == -1) {
							return;
						}
						var r = first.substring(0, index);
						for (var i = 1; i < arr.length; i++) {
							r += '#' + arr[i];
						}
						console.log("更改链接", url, r);
						window.history.pushState(null, null, r);
					} catch (e) {
						console.log("更改链接报错:", e);
					}
				}

				setTimeout(() => {
					changeH5Url();
				}, 500);
				return;
			} else {
				showMsg('获取openid失败,请刷新重试');
				return;
			}
		});
	} else {
		getAuthorizeUrl(window.location.href);
		return;
	}
}

const getAuthorizeUrl = function (href) {
	showToast("重新获取微信openid");
	var locationHref = encodeURIComponent(href);
	// var goToUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" +
	//     weixinAppID +
	//     "&redirect_uri=" +
	//     url +
	//     "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
	//https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE&component_appid=component_appid#wechat_redirect
	// var url = config.wxOpenUrl + "Open/GetCode?redirectUrl=" + locationHref;
	// var goToUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" +
	//     weixinAppID +
	//     "&redirect_uri=" +
	//     encodeURIComponent(url) +
	//     "&response_type=code&scope=snsapi_userinfo&state=STATE&component_appid=" + config.sAppID +
	//     "#wechat_redirect";
	//window.location.href = goToUrl;
	var postData = tool.toKeyValue({
		redirectUrl: locationHref
	});
	tool.post('api/Login/GetAuthorizeUrl', postData).then((data) => {
		if (data.Success) {
			window.location.href = data.Result;
		}
	});
}

export default {
	baseVM,
	getToken,
	setToken,
	getWechatToken,
	setWechatToken,
	isWechat,
	showMsg,
	loginSuccess,
	showToast,
	confirm,
	prompt,
	init,
	tool,
	lodash,
	getApp,
	getDeviceId,

	getAuthorizeUrl
}
